import Vue from 'vue';
import { Subject, Subscription } from 'rxjs';
import { Component, Prop } from 'vue-property-decorator';
import { IPSAppView, IPSControl, IPSDEForm, IPSDEFormDetail, IPSDEFormItem, IPSDEFormPage, IPSDEGrid, IPSDEGridColumn } from '@ibiz/dynamic-model-api';
import { CtrlType, ISheetCtrl, ISheetParam } from '../../interface';
import './app-ctrl-design.less';

@Component({})
export class AppCtrlDesign extends Vue {

  /**
   * @description 视图实例对象
   * @type {IPSAppView}
   * @memberof AppCtrlDesign
   */
  @Prop() public viewInstance!: IPSAppView;

  /**
   * @description sheet状态通知对象
   * @type {Subject<ISheetParam>}
   * @memberof AppCtrlDesign
   */
  @Prop() public sheetState !: Subject<ISheetParam>;

  /**
   * sheet状态事件
   *
   * @public
   * @type {(Subscription | undefined)}
   * @memberof AppCtrlDesign
   */
  public sheetStateEvent: Subscription | undefined;

  /**
   * @description 是否显示抽屉
   * @type {boolean}
   * @memberof AppCtrlDesign
   */
  public showDrawer: boolean = false;

  /**
   * @description 是否具有激活部件
   * @type {boolean}
   * @memberof AppCtrlDesign
   */
  public isActiveCtrl: boolean = false;

  /**
   * @description 表格列
   * @type {any[]}
   * @memberof AppCtrlDesign
   */
  public columns: any[] = [];

  /**
   * @description 表单项
   * @type {any[]}
   * @memberof AppCtrlDesign
   */
  public formItems: any[] = [];

  /**
   * @description 部件类型集合
   * @type {any[]}
   * @memberof AppCtrlDesign
   */
  public types: any[] = [
    {
      key: CtrlType.CTRL,
      name: '普通控件'
    },
    {
      key: CtrlType.VISUAL_GRID,
      name: '虚拟表格',
      controlType: 'GRID'
    },
    {
      key: CtrlType.VISUAL_FORM,
      name: '虚拟表单',
      controlType: 'FORM'
    }
  ];

  /**
   * @description 基础配置
   * @type {*}
   * @memberof AppCtrlDesign
   */
  public options: any = {};

  /**
   * @description 部件初始化
   * @memberof AppCtrlDesign
   */
  public created() {
    this.handleOptions();
    if (this.sheetState) {
      this.sheetStateEvent = this.sheetState.subscribe(({ tag, action, data }: { tag: string, action: string, data: any }) => {
        if (!Object.is(tag, 'design')) {
          return;
        }
        if (Object.is(action, 'OPEN')) {
          this.handleOptions(data);
          this.showDrawer = true;
        }
        if (Object.is(action, 'REFRESH')) {
          this.handleOptions(data);
        }
        if (Object.is(action, 'CLOSE')) {
          this.closeDrwaer();
        }
      })
    }
  }

  /**
   *  @description 组件销毁
   * 
   * @memberof AppCtrlDesign
   */
  public destory() {
    if (this.sheetStateEvent) {
      this.sheetStateEvent.unsubscribe();
    }
  }

  /**
   * @description 处理配置
   * @param {ISheetCtrl} [opt]
   * @memberof AppCtrlDesign
   */
  public handleOptions(opt?: ISheetCtrl) {
    const options = {
      id: '',
      codeName: '',
      row: 0,
      rowCount: 0,
      col: 0,
      left: 0,
      top: 0,
      width: 100,
      height: 100,
      startRow: 0,
      startCol: 0,
      type: CtrlType.CTRL
    }
    if (opt) {
      this.isActiveCtrl = true;
      const { id, position, type, codeName, columns, items } = opt;
      Object.assign(options, {
        id: id,
        codeName: codeName,
        row: position?.row || 0,
        col: position?.col || type == CtrlType.VISUAL_FORM ? 24 : 0,
        startRow: position?.startRow || 0,
        startCol: position?.startCol || 0,
        left: position?.left || 0,
        top: position?.top || 0,
        width: position?.width || 100,
        height: position?.height || 100,
        type: type,
        columns: columns,
        items: items
      });
    }
    this.options = options;
    if (opt && opt.type == CtrlType.VISUAL_GRID) {
      this.initGridColumns(opt.id, true);
    } else if (opt && opt.type == CtrlType.VISUAL_FORM) {
      this.initFormItems(opt.id, true);
    }
  }

  /**
   * @description 获取部件
   * @param {string} id 标识
   * @param {IPSControl[]} [controls] 部件集合，不传默认为视图实例部件集合
   * @return {*} 
   * @memberof AppCtrlDesign
   */
  public getControl(id: string, controls?: IPSControl[]) {
    const viewControls = controls ? controls : this.viewInstance.getPSControls() || [];
    return viewControls.find((control: IPSControl) => {
      return `${this.options.type}-${control.codeName}-${control.controlType}` == id;
    });
  }

  /**
   * @description 获取提交数据
   * @return {*}  {ISheetCtrl}
   * @memberof AppCtrlDesign
   */
  public getSubmitData(): ISheetCtrl {
    const { id, type, row, col, left, top, width, height, startRow, startCol, items } = this.options;
    const control = this.getControl(id);
    const data = {
      id: id,
      name: control?.name || '',
      codeName: control?.codeName || '',
      type: type
    };

    if (type == CtrlType.CTRL) {
      Object.assign(data, {
        position: {
          left: left,
          top: top,
          width: width,
          height: height
        }
      })
    } else if (type == CtrlType.VISUAL_GRID) {
      const columns: any[] = [];
      this.columns.forEach((column: any) => {
        if (column.checked) {
          columns.push(column.codeName);
        }
      });
      Object.assign(data, {
        columns: columns,
        position: {
          startRow: startRow,
          startCol: startCol
        }
      })
    } else if (type == CtrlType.VISUAL_FORM) {
      Object.assign(data, {
        position: {
          startRow: startRow,
          startCol: startCol,
          row: row,
          col: col
        },
        items: this.isActiveCtrl ? items : []
      })
    }
    return data;
  }

  /**
   * @description 提交数据
   * @memberof AppCtrlDesign
   */
  public submit() {
    this.$emit('change', this.getSubmitData());
  }

  /**
   * @description 关闭抽屉
   * @memberof AppCtrlDesign
   */
  public closeDrwaer() {
    this.showDrawer = false;
    this.handleOptions();
    this.columns = [];
    this.isActiveCtrl = false;
  }

  /**
   * @description 处理部件选择变化
   * @memberof AppCtrlDesign
   */
  public handleControlChange() {
    const { type, id } = this.options;
    if (type == CtrlType.VISUAL_GRID) {
      this.initGridColumns(id);
    } else if (type == CtrlType.VISUAL_FORM) {
      this.initFormItems(id);
    }
  }

  /**
   * @description 渲染部件
   * @return {*} 
   * @memberof AppCtrlDesign
   */
  public renderControls() {
    const controlType = this.types.find((type: any) => type.key == this.options.type)?.controlType || '';
    let controls: IPSControl[] = [];
    const viewControls = this.viewInstance.getPSControls() || [];
    if (controlType != '') {
      controls = viewControls.filter((control: IPSControl) => { return control.controlType == controlType });
    } else {
      controls = viewControls;
    }
    if (!this.getControl(this.options.id, controls)) {
      this.options.id = '';
    }
    return (
      <el-form-item label="部件">
        <el-select v-model={this.options.id} onChange={() => { this.handleControlChange(); }}>
          {controls.map((control: IPSControl) => {
            const { codeName, controlType } = control;
            return (
              <el-option key={`${this.options.type}-${codeName}-${controlType}`} value={`${this.options.type}-${codeName}-${controlType}`} label={control.logicName}>
              </el-option>
            )
          })}
        </el-select>
      </el-form-item>
    )
  }

  /**
   * @description 渲染通用部件配置
   * @return {*} 
   * @memberof AppCtrlDesign
   */
  public renderCommonCtrlOpt() {
    return (
      <div class="design--ctrl-opt common-ctrl--opt">
        <el-form-item label="左侧距离" prop="left">
          <el-input-number v-model={this.options.left} min={0} />
        </el-form-item>
        <el-form-item label="上方距离" prop="top">
          <el-input-number v-model={this.options.top} min={0} />
        </el-form-item>
        <el-form-item label="宽度" prop="width">
          <el-input-number v-model={this.options.width} step={50} min={0} />
        </el-form-item>
        <el-form-item label="高度" prop="height">
          <el-input-number v-model={this.options.height} step={50} min={0} />
        </el-form-item>
      </div>
    )
  }

  /**
   * @description 初始化表格列
   * @param {string} id
   * @memberof AppCtrlDesign
   */
  public initGridColumns(id: string, isInit: boolean = false) {
    const columns = (this.getControl(id) as IPSDEGrid)?.getPSDEGridColumns?.() || [];
    const tempColumns: any[] = [];
    const initColumns: any[] = this.options.columns || [];
    const _columns = isInit ? initColumns.map((column: any, index: number) => {
      return {
        codeName: column,
        checked: true,
        index: index - initColumns.length // 用于排序
      }
    }) : this.columns;
    columns.forEach((column: IPSDEGridColumn, index: number) => {
      const tempColumn = _columns.find((_column: any) => { return _column.codeName == column.codeName });
      tempColumns.push({
        codeName: column.codeName,
        label: column.caption,
        checked: isInit ? tempColumn ? true : false : tempColumn && !tempColumn.checked ? false : true,
        index: tempColumn ? tempColumn.index : index
      })
    });
    //  排序
    this.columns = [...tempColumns.sort(((a: any, b: any) => {
      return a.index > b.index ? 1 : -1
    }))];
  }

  /**
   * @description 初始化表单项
   * @param {string} id 唯一标识
   * @param {boolean} [isInit=false]
   * @memberof AppCtrlDesign
   */
  public initFormItems(id: string, isInit: boolean = false) {
    const form = this.getControl(id) as IPSDEForm;
    const items: any[] = [];
    const getDetails = (detail: IPSDEFormDetail) => {
      const details = (detail as any).getPSDEFormDetails?.() || [];
      if (details && details.length) {
        details.forEach((item: IPSDEFormDetail) => {
          getDetails(item);
        })
      }
      if (detail.detailType == 'FORMITEM') {
        items.push(detail);
      }
    }
    if (form) {
      (form.getPSDEFormPages() || []).forEach((page: IPSDEFormPage) => {
        getDetails(page);
      });
    }
    this.formItems = [...items];
  }

  /**
   * @description 渲染表格列
   * @return {*} 
   * @memberof AppCtrlDesign
   */
  public renderGridColumns() {
    if (this.options.id && this.columns.length) {
      return (
        <draggable v-model={this.columns} handle=".drag-icon">
          {this.columns.map((column: any) => {
            return (
              <div class="check-control">
                <el-checkbox
                  checked={column.checked}
                  key={column.codeName}
                  label={column}
                  onChange={(value: boolean) => { column.checked = value; }}>
                  {column.label}
                </el-checkbox>
                <i class="el-icon-rank drag-icon" />
              </div>
            )
          })}
        </draggable>
      )
    }
  }

  /**
   * @description 渲染虚拟表格配置
   * @return {*} 
   * @memberof AppCtrlDesign
   */
  public renderVisualGridOpt() {
    return (
      <div class="design--ctrl-opt visual-grid--opt">
        <el-form-item label="起始行" prop="row">
          <el-input-number v-model={this.options.startRow} min={0} />
        </el-form-item>
        <el-form-item label="起始列" prop="col">
          <el-input-number v-model={this.options.startCol} min={0} />
        </el-form-item>
        {/* <el-form-item label="行数" prop="rowCount">
          <el-input-number v-model={this.options.rowCount} min={0} />
        </el-form-item>
        <el-form-item label="左侧距离" prop="left">
          <el-input-number v-model={this.options.left} min={0} />
        </el-form-item>
        <el-form-item label="上方距离" prop="top">
          <el-input-number v-model={this.options.top} min={0} />
        </el-form-item> */}
        {this.renderGridColumns()}
      </div>
    )
  }

  public renderFormItem() {
    if (this.options.id) {
      return (
        <div class="form--opt__items">
          {this.formItems.map((item: IPSDEFormDetail) => {
            return (
              <div class="form--opt__item">
                {item.caption}
              </div>
            )
          })}
        </div>
      )
    }
  }

  /**
   * @description 渲染虚拟表单配置
   * @return {*} 
   * @memberof AppCtrlDesign
   */
  public renderVisualFormOpt() {
    //  表单列默认 24 列
    this.options.col = 24;
    return (
      <div class="design--ctrl-opt visual-form--opt">
        <el-form-item label="起始行" prop="startRow">
          <el-input-number v-model={this.options.startRow} disabled min={0} />
        </el-form-item>
        <el-form-item label="起始列" prop="startCol">
          <el-input-number v-model={this.options.startCol} disabled min={0} />
        </el-form-item>
        <el-form-item label="行数" prop="row">
          <el-input-number v-model={this.options.row} min={0} />
        </el-form-item>
        <el-form-item label="列数" prop="col">
          <el-input-number v-model={this.options.col} disabled step={2} min={0} />
        </el-form-item>
      </div>
    )
  }

  /**
   * @description 根据类型渲染部件配置
   * @return {*} 
   * @memberof AppCtrlDesign
   */
  public renderCtrlOptByType() {
    const type = this.options.type;
    if (type == CtrlType.CTRL) {
      return this.renderCommonCtrlOpt();
    } else if (type == CtrlType.VISUAL_GRID) {
      return this.renderVisualGridOpt();
    } else if (type == CtrlType.VISUAL_FORM) {
      return this.renderVisualFormOpt();
    }
  }

  /**
   * @description 渲染部件
   * @return {*} 
   * @memberof AppCtrlDesign
   */
  render() {
    return (
      <div class="app-sheet-design">
        <div class="custom-design-button" onClick={() => { this.showDrawer = true; }}>设计</div>
        <el-drawer
          visible={this.showDrawer}
          modal={false}
          custom-class="sheet-design--drawer"
          size="260px"
          title={this.options?.codeName ? `设计 - ${this.options.codeName}` : '设计'}
          onClose={() => { this.closeDrwaer() }}
          on={{
            "update:visible": (state: boolean) => {
              this.showDrawer = state;
            }
          }}>
          <el-form
            size="mini"
            class="design--form"
            label-width="80px"
            props={{
              model: this.options
            }}>
            <div class="design--ctrl-type">
              <el-form-item>
                <el-radio-group v-model={this.options.type}>
                  {this.types.map((type: any) => {
                    return (
                      <el-radio-button
                        v-model={type.key}
                        label={type.key}
                        disabled={this.isActiveCtrl ? this.options.type == type.key ? false : true : false}>
                        {type.name}
                      </el-radio-button>
                    )
                  })}
                </el-radio-group>
              </el-form-item>
            </div>
            {this.renderControls()}
            {this.renderCtrlOptByType()}
            <div class="design--footer">
              <el-button type="primary" onClick={() => { this.submit(); }}>确认</el-button>
              <el-button onClick={() => { this.showDrawer = false; }}>取消</el-button>
            </div>
          </el-form>
        </el-drawer>
      </div>
    )
  }
}